package com.gjt.URI_URL;


import java.io.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection;

/**
 * Created with Intel IDEA.
 * Uri(统一资源标识符):由模式，授权机构（用户名，口令，主机，端口），路径，查询 ，片段（从技术上讲它是URL的引用而不是URL）
 *      特点：只能标识资源，一旦构建了其中的字段是不再改变，线程安全
 *
 *      例子：http://www.baidu.com/root/user/test.txt 这个uri表示映射到一个资源
 *
 *          http://www.baidu.com/root/user/？inkey=10-63474674 查询为 inkey=10-63474674
 *
 *          ftp://mp3:mp3@ci4198-a.ashvill.nc.home.com:33/test.mp3 授权机构mp3:mp3@ci4198-a.ashvill.nc.home.com:33
 *              这个授权机构由用户名：mp3 ,口令：mp3,主机：ci4198-a.ashvill.nc.home.com 和 端口33(一般uri中不包含口令)
 *
 *          要表示书名 java I/O  则 /  用%2F表示    空格 用%20表示
 *           http://www.baidu.com/root/user/java%20I%2FO
 *
 *           相对URL： http://www.baidu.com/root/user/1.html
 *                    中有<a href="2.html" />  点击之后 会把地址的1.html去除 将2.html添加
 *                    允许将整个文档树从一个网站移动或者复制到另一个网站不会破坏所有的内部链接
 *
 * Url(统一资源定位器)：是一个URI ，还可以为资源提供一个特定的网络位置
 *             构造方法: Url(String url)
 *                     Url(String protocol , String hostname , String file)
 *                     Url(String protocol , String host ,int port , String file)
 *                     Url(Url base , String relative)
 *
 *             从url获取数据的方法：openStream()获取URL中的输入流
 *                              openConnection() 为指定的URL 打开一个socket ，返回一个URLConnection对象
 *                              getContent() 获取由url引用的数据，尝试由他建立某种类型的对象。 Url 指向文本则返回的某种InputStream
 *                              getContent(Class[] classes)
 *
 *             获取url中信息的方法：
 *                              getProtocol() 获取url的模式 返回String
 *                              getHost()  获取URL 的主机名 返回String
 *                              getPort() 获取url 中的端口 没有的话就返回-1(url必须显示有端口)
 *                              getDefault()  获取url 中的默认端口
 *                              getFile() 获取url 包含路径部分（从主机名后的第一个斜线一直到片段标识符之前 #; 包含查询字符串 ）
 *                              getPath() 获取 url中的路径和文件部分不包含查询字符串
 *                              getRef() 获取 url的片段标识符部分（没有 返回null ）
 *                              getQuery() 获取 url的查询字符串
 *                              getUserInfo() 获取 url 的用户名，或者口令 （ 可用@ 符号可以将用户信息和主机分开） 例如http://user@java.org/
 *                              getAuthority()  获取 url 中的授权机构（包括用户信息，主机，端口）
 *
 *              相等性和比较：URL主机，端口，路径，片段标识符 查询字符串 都相同 两个URL才相等
 *                          equals() 会尝试DNS解析主机 http://www.ibiblio.org和http://ibiblio.org 一样（只是URL一样
 *                                  但指向的资源是否一样不能判断） 注意：url的equals（）可能是阻塞I/o 尽量转成URI
 *                          sameFile(Url other): 检查两个url 是否指向同一个资源（不考虑片段标识符）
 *                                    即 http://ibiblio.org/1.txt#q1 和 http://ibiblio.org/1.txt#q1 一样
 *
 *                          URL的3个方法可以将实例转换成另一种形式
 *                              toString(),toExternalForm(),toURI()
 *  注意 URL一般使用get请求      URLConnection：用与post请求
 *
 * @Auther: gjt
 * @Date: 2024/3/22 10:35
 */
public class Url {

    public static void main(String[] args) {


        // 超文本传输协议
        testProtocol("http://www.adc.org");

        // 安全的http
        testProtocol("https://www.adc.org");

        // 文件传输协议
        testProtocol("ftp://ibiblio.org/pub");

        // 简单邮件传输协议
        testProtocol("mail:elharo@ibiblio.org");

        // telnet
        testProtocol("telnet://dibner.poly.edu/");

        // 本地文件访问
        testProtocol("file:///etc/password");

        /**
         * case 1: 从url获取数据   openStream()获取URL中的输入流
         */
        InputStream inputStream = null;
        try{
            // URL不一定指向的文本
            java.net.URL url = new java.net.URL("http://gjt1314.xyz/");
            // 从url中 获取数据流
            inputStream = url.openStream();

            inputStream = new BufferedInputStream(inputStream);
            Reader reader = new InputStreamReader(inputStream);
            int c;
            char[] bytes = new char[1024];
            while((c = reader.read(bytes)) != -1 ){
                System.out.println(new String(bytes));
            }

        }catch (IOException e){
            e.printStackTrace();
        }finally {
            try{
                if(inputStream !=null) inputStream.close();
            }catch (IOException ex){
                ex.printStackTrace();
            }
        }


        /**
         * case 2: 从url获取数据  openConnection() 为指定的URL 打开一个socket ，返回一个URLConnection对象
         *          URLConnection标识一个网络资源的打开连接, 可以从中获取输入流
         */

        try{
            URL url = new URL("http://gjt1314.xyz/");
            URLConnection urlConnection = url.openConnection();
            try(InputStream in = urlConnection.getInputStream()){
                BufferedReader reader = new BufferedReader(new InputStreamReader(in));
                char[] list = new char[1024];
                int c;
                while((c = reader.read(list)) != -1){
                    System.out.println(list);
                }
            }catch (IOException e){
                e.printStackTrace();
            }
        }catch (IOException e){
            e.printStackTrace();
        }


        /**
         * case 3:  从url获取数据 getContent() 获取由url引用的数据，尝试由他建立某种类型的对象。 Url 指向文本则返回的某种InputStream
         *          如果url指向图像则返回java.awt.ImageProducer
         *          特点：很难预测获取那种对象
         */

        try{
            java.net.URL url = new java.net.URL("https://cn.bing.com/images/search?view=detailV2&ccid=7KW5GT7N&id=B33EDD" +
                    "D4B70A8010E22B0F97BA60CB4FD398A3EA&thid=OIP.7KW5GT7NQ8yUGlBbCHEm0gHaNK&mediaurl" +
                    "=https%3a%2f%2fuploadfile.bizhizu.cn%2f2017%2f0701%2f20170701031428774.jpg&exph=" +
                    "1820&expw=1024&q=%e5%9b%be%e7%89%87&simid=608051637613970875&FORM=IRPRST&ck=E1B" +
                    "BBB9CFBB09107848743CC6B98B04B&selectedIndex=0&itb=0&idpp=overlayview&ajaxhist=0&ajaxserp=0");
            Object content = url.getContent();
            System.out.println("获取"+content.getClass().getName());
        }catch (IOException e){
            e.printStackTrace();
        }

        /**
         * case 4 : 从url获取数据 getContent(Class[] classes)
         */

        try{
            java.net.URL url = new java.net.URL("https://www.chinanews.com.cn/");
            Class<?>[] types= new Class[3];

            types[0] = String.class;
            types[1] = Reader.class;
            types[2] = InputStream.class;

            Object content = url.getContent(types);
            if( content instanceof String){
                System.out.println(content);
            }else if(content instanceof Reader){
                try(BufferedReader buf= new BufferedReader((Reader) content)){
                    char[] list = new char[1024];
                    int c;
                    while((c = buf.read(list)) != -1){
                        System.out.println(list);
                    }
                }catch (IOException ez){
                    ez.printStackTrace();
                }
            }else if(content instanceof InputStream){
                try( InputStream in= (InputStream)content){

                    byte[] list = new byte[1024];
                    int c;
                    while((c = in.read()) != -1){
                        System.out.println(list);
                    }
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
        }catch (IOException e){
            e.printStackTrace();
        }


        /**
         * case 5： url 的只读访问
         */
        try{
            java.net.URL url = new java.net.URL("http://www.baidu.com");
            // 获取url的模式 返回String
            String protocol = url.getProtocol();
            System.out.println(protocol);

            // 获取URL 的主机名 返回String
            String host = url.getHost();
            System.out.println(host);

            // 获取url 中的端口 没有的话就返回-1(url必须显示有端口)
            int port = url.getPort();
            System.out.println(port);

            // 获取url 中的默认端口
            int defaultPort = url.getDefaultPort();
            System.out.println(defaultPort);

            // 获取url 包含路径部分（从主机名后的第一个斜线一直到片段标识符之前 #; 包含查询字符串 ）
            String file = url.getFile();
            System.out.println(file);

            // 获取 url中的路径和文件部分不包含查询字符串
            String path = url.getPath();
            System.out.println(path);

            // 获取 url的片段标识符部分（没有 返回null ）
            String ref = url.getRef();
            System.out.println(ref);

            // 获取 url的查询字符串
            String query = url.getQuery();
            System.out.println(query);

            // 获取 url 的用户名，或者口令 （ 可用@ 符号可以将用户信息和主机分开） 例如http://user@java.org/
            String userInfo = url.getUserInfo();
            System.out.println(userInfo);

            // 获取 url 中的授权机构（包括用户信息，主机，端口）
            String authority = url.getAuthority();
            System.out.println(authority);
        }catch (IOException e){
            e.printStackTrace();
        }


    }


    /**
     *  检测是否支持协议（使用字符串构造URL）
     * @param url 域名一般是
     */
    private static void testProtocol(String url){
        try{
            // 如果构建不会成功则会抛出MalformedURLException 异常（即可以判断）
            java.net.URL u = new java.net.URL(url);
            System.out.println("支持 "+u.getProtocol() + " 协议");
        }catch (MalformedURLException e){
            String protocol = url.substring(0, url.indexOf(":"));
            System.out.println("不支持 "+ protocol + " 协议");
            }
    }

    /**
     *  多参构造URL
     */
    private static void createHasArgument(){
        try{
            java.net.URL url = new java.net.URL("http", "gjt1314yy.xyz", 80, "/html/csapp.html#intro");
            System.out.println("支持 "+url.getProtocol() + " 协议");
        }catch (MalformedURLException e){
            e.printStackTrace();
        }
    }

    /**
     * 构造相对URL
     */
    private static  void createRelative(){
        try{
            java.net.URL u1 = new java.net.URL("http://www.baidu.com/1.html");
            java.net.URL url = new java.net.URL(u1, "mailling.html");
        }catch (MalformedURLException e){
            e.printStackTrace();
        }
    }


    /**
     * 其他URL对象来源
     */

    private static  void createURL(){
        try{
            // 文件获取URL
            File sss = new File("sss");
            java.net.URL url = sss.toURL();

            // 通过类加载器获取URL
            java.net.URL systemResource = ClassLoader.getSystemResource("hello.txt");

        }catch (MalformedURLException e){
            e.printStackTrace();
        }
    }
}
